package com.hs.javassist;


import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;

import java.lang.reflect.Method;

public class JavassistTest {

    /**
     * @param args
     */
    public static void main(String[] args) {

        CtClass ctClass;
        try {
            // 用于取得字节码类，必须在当前的classpath中，使用全称
            ctClass = ClassPool.getDefault().get("com.hs.javassist.A");
            // 需要修改的方法名称
            String mname = "method";
            CtMethod mold = ctClass.getDeclaredMethod(mname);
            // 修改原有的方法名称
            String nname = mname + "$impl";
            mold.setName(nname);

            // 创建新的方法，复制原来的方法
            CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);

            // 主要的注入代码
            StringBuffer body = new StringBuffer();
            body.append("{\nlong start = System.currentTimeMillis();\n");
            body.append("\nSystem.out.println(1024);\n");
            // 调用原有代码，类似于method();($$)表示所有的参数
            body.append(nname + "($$);\n");
            body.append("System.out.println(\"Call to method " + mname
                    + " took \" +\n (System.currentTimeMillis()-start) + "
                    + "\" ms.\");\n");

            body.append("}");
            // 替换新方法
            mnew.setBody(body.toString());
            // 增加新方法
            ctClass.addMethod(mnew);
            // 类已经更改，注意不能使用A a=new A();，因为在同一个classloader中，不允许装载同一个类两次
            //A a1=new A();a1.method();
            //不过先加载类后（未初始化），再new 对象就没关系了。toClass做了类加载的操作
            Class aClass = ctClass.toClass();
            A a1=new A();a1.method();
            A a = (A) aClass.newInstance();
            for (Method method : a.getClass().getMethods()) {
                //System.out.println(method.getName());
            }
            a.method();
        } catch (NotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CannotCompileException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {

        }
    }

}